home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Book Chapters
/
00 - Game Programming Primer
/
HelloWorld5.c
< prev
next >
Wrap
Text File
|
1995-06-29
|
26KB
|
555 lines
//==============================================================================================\\
// ----------------------------------------------------------------------------------- \\
// HelloWorld5.c version 1.0.0 copyright © 1993…1995 Jamie McCornack, john calhoun \\
// ----------------------------------------------------------------------------------- \\
// Demo program for Macintosh GameWriter 1.0.0, a training program… \\
// …for beginning Mac game programmers. MGW1 includes MGWExterns1.h, MGWUtilities1.c,… \\
// …MGWSound1.c, MGWGraphics1.c, MGWGraphicsBWLite1.c, HelloWorld.rsrc and an assortment… \\
// …of demo programs; projects HelloWorld1.π etc. and source code files HelloWorld1.c etc. \\
// A tutorial is available in Tricks of the Mac Game Programming Gurus, published… \\
// …by Hayden Books, August 1995. \\
// \\
// This code is offered by the copyright holders for no fee and for whatever use… \\
// …you care to make of it, but we do hope you remember where it came from. \\
// \\
// Please send bug reports to MacGameDev at America OnLine. macgamedev@aol.com \\
// Suggestions and observations are also appreciated. \\
// Updates and upgrades will be available now and then from the above e-mail address. \\
//==============================================================================================\\
// This program opens a window, displays a color background suitable for whatever color or…
// …grayscale depth the main monitor is set for, and at first…
// …mouseclick, runs two clams across the screen. At second mouseclick, one clam stops,…
// …talks, and flaps its/his/her face for 40 frames as the other clam continues running.
// When the other clam runs up to the standing clam, there is an impact.
// Note: departure from text--for monitors deeper than 8-bit, default is 256 colors. The PICTs…
// …get huge over 8-bit, and you get annoyances like heap space problems.
#include "MGWExterns1.h"
#define kPutInFront (WindowPtr)-1L
#define kWaitTicks 4L // Sets the delay in Ticks between frames. Try 3. Try 2. Try 0.
#define kJaneStepLength 12 // Sets the distance in pixels between Clamity Jane's moves.
#define kClemStepLength 16 // Sets the distance in pixels between Clem the Clam's moves.
#define kFrontFace 0 // Enumerates the various faces of the clam sprites.
#define kBlinkFace 1
#define kEehFace 2
#define kOohFace 3
#define kStepRightFace 4
#define kWalkRightFace 5
#define kRunRightFace 6
#define kDizzyRightFace1 7
#define kDizzyLeftFace1 8
#define kDizzyRightFace2 9
#define kDizzyLeftFace2 10
#define kMaxFaces 11
#define kBounce -2 // Sets how many steps the running clam bounces back on impact.
#define kLastFace 40 // Sets how many frames the clams stay visible after impact.
// The resource constants--with 'r' prefix like Apple wants them.
#define rJaneFaces1ID 129 // The 'PICT' ID# where the views of Jane are located.
#define rClemFaces1ID 129 // The 'PICT' ID# where the views of Clem are located.
#define rBackground1ID 128 // The 'PICT' ID# where the background picture is located.
#define rJaneFaces4ID 133 // The 'PICT' ID# where the views of Jane are located.
#define rClemFaces4ID 132 // The 'PICT' ID# where the views of Clem are located.
#define rBackground4ID 131 // The 'PICT' ID# where the background picture is located.
#define rJaneFaces8ID 136 // The 'PICT' ID# where the views of Jane are located.
#define rClemFaces8ID 135 // The 'PICT' ID# where the views of Clem are located.
#define rBackground8ID 134 // The 'PICT' ID# where the background picture is located.
#define rMasksID 130 // The 'PICT' ID# where the clam masks are located.
#define rMainWindowID 128 // The 'WIND' resource ID# for the main window.
#define rHelloSndID 3000
#define rFootstepSndID 3001
#define rImpactSndID 3002
#define rDizzySndID 3003
// #define kColorBitsNeeded 8
typedef struct
{
Rect face;
Rect mask;
} tSpriteType;
Rect bigPictureRect, masksRect, allComboRect;
Rect janeFacesRect, janeIsAtRect, janeWasAtRect, janeComboRect;
Rect clemFacesRect, clemIsAtRect, clemWasAtRect, clemComboRect;
CGrafPtr workCPort, janeFacesCPort, clemFacesCPort, backgroundCPort;
GrafPtr mainWindow, masksPort;
Boolean itWorked, contactFlag, impactReadyFlag, gameOverFlag, evenFrame; // Note new flags.
long targetTick;
short janeSprite, clemSprite, thisFaceCounter;
short bestJaneFacesID, bestClemFacesID, bestBackgroundID;
tSpriteType sprite[kMaxFaces];
extern Boolean gUserWantsSound;
//============================================================== Prototypes
void InitAll(void);
void SetBestPICTs (void);
void OpenMainWindow (void);
void SetTheRects(void);
void SetTheCPorts(void);
void CopyBothAtOnce (void);
void CopyOneAtATime (void);
void ShowClams (void);
void DoDelay (void);
void JaneLoop (void);
void ClemLoop (void);
void JaneSpeaks (void);
void DoImpact (void);
//============================================================== Functions
//-------------------------------------------------------------- InitAll
void InitAll(void)
{
InitToolbox();
// if (WhatsOurDepth() != kColorBitsNeeded) // Don't need this right now,…
// RedAlert(kErrNot8BitColor); // …since we're not insisting on any particular depth.
SetBestPICTs();
gUserWantsSound = TRUE;
InitializeForSound();
SetTheRects(); // Since some of these Rects define fields in CGrafPorts,…
SetTheCPorts(); // …set the rects before setting the ports.
janeSprite = kStepRightFace;
clemSprite = kRunRightFace;
thisFaceCounter = 0;
contactFlag = FALSE; // Not touching,
impactReadyFlag = FALSE; // Not about to collide,
gameOverFlag = FALSE; // Not done playing.
evenFrame = TRUE;
targetTick = TickCount() + kWaitTicks;
HideCursor(); // This demo doesn't use mouse input, so why look at it?
}
//-------------------------------------------------------------- SetBestPICTs
void SetBestPICTs (void) // Selects the best PICTs for current monitor pixel depth.
{ short thisDepth;
thisDepth = WhatsOurDepth();
switch (thisDepth)
{ case (1): // Black and white, which won't run with pixmaps. Gotta quit.
{ RedAlertString("\pThis program requires color or grayscale"); // Our error routine.
break; }
case (2): // 4 grays.
{ bestBackgroundID = rBackground1ID;
bestClemFacesID = rClemFaces1ID;
bestJaneFacesID = rJaneFaces1ID;
break; }
case (4): // 16 colors or grays.
{ bestBackgroundID = rBackground4ID;
bestClemFacesID = rClemFaces4ID;
bestJaneFacesID = rJaneFaces4ID;
break; }
default: // Millions of colors.
{ bestBackgroundID = rBackground8ID;
bestClemFacesID = rClemFaces8ID;
bestJaneFacesID = rJaneFaces8ID;
break; }
}
}
//-------------------------------------------------------------- OpenMainWindow
void OpenMainWindow (void)
{
mainWindow = GetNewCWindow(128, 0L, kPutInFront); // Load window from resource.
ShowWindow((GrafPtr)mainWindow); // Now display it.
SetPort((GrafPtr)mainWindow); // Make its port current.
ClipRect(&bigPictureRect); // Set its clip region.
CopyRgn(mainWindow->clipRgn, mainWindow->visRgn); // Set its visRgn.
ForeColor(blackColor); // Set its pen color to black.
BackColor(whiteColor); // Set background color white.
}
//-------------------------------------------------------------- SetTheRects
void SetTheRects(void) // The most tedious part of programming this type of game.
{
SetRect(&janeFacesRect, 0, 0, 448, 64); // Size and shape of BitMap for the sprite faces.
SetRect(&clemFacesRect, 0, 0, 448, 64); // Size and shape of BitMap for the sprite faces.
SetRect(&masksRect, 0, 0, 448, 32); // Size and shape of BitMap for the sprite masks.
SetRect(&bigPictureRect, 0, 0, 512, 322); // The shape of the picture we'll put in the main window, workCPort and backgroundCPort.}
SetRect(&janeIsAtRect, 80, 240, 112, 272); // The shape (32 x 32) of the images of Jane, and the position of the first image.}
janeWasAtRect = janeIsAtRect; // Initializing janeIsAtRect...it has to start somewhere, and this is handy.}
janeComboRect = janeIsAtRect;
SetRect(&clemIsAtRect, 40, 244, 72, 276); // The shape (32 x 32) of the images of Clem, and the position of the first image.}
clemWasAtRect = clemIsAtRect; // Initializing clemIsAtRect...it has to start somewhere, and this is handy.}
clemComboRect = clemIsAtRect;
// And now, the tedium. In this sample, all we're doing is showing the clam running across the screen to the right.}
// However, if you use ResEdit and look at 'PICT' 129 in Sample.rsrc, you'll find 28 different views of the clam.}
// If we wanted the clam to run left too, and walk slowly, and face the user, and blink its eyes, we'd be calling…}
// …SetRect 56 times--one face and one mask per sprite. And if we had jumping clams and rear views of clams…}
// …and starfish and clamdiggers and other hazards of the clam environment, we might have hundreds of rects to set.}
SetRect(&sprite[kFrontFace].face, 320, 32, 352, 64); // The shape and position of sprite[kFrontFace].face on facesCPort.portPixMap.
SetRect(&sprite[kFrontFace].mask, 320, 0, 352, 32); // The shape and position of sprite[kFrontFace].mask on masksPort.portPixMap.
SetRect(&sprite[kBlinkFace].face, 320, 0, 352, 32); // Note that some faces (e.g. eyes open or closed) use the same mask,…
SetRect(&sprite[kBlinkFace].mask, 320, 0, 352, 32); // …since they have the same silhouette.}
SetRect(&sprite[kEehFace].face, 352, 0, 384, 32); // I could write more comments here, but setting these rects…
SetRect(&sprite[kEehFace].mask, 352, 0, 384, 32); // …is already tedious enough without a bunch of busy-work.
SetRect(&sprite[kOohFace].face, 352, 32, 384, 64);
SetRect(&sprite[kOohFace].mask, 352, 0, 384, 32);
SetRect(&sprite[kStepRightFace].face, 192, 0, 224, 32);
SetRect(&sprite[kStepRightFace].mask, 192, 0, 224, 32);
SetRect(&sprite[kWalkRightFace].face, 224, 0, 256, 32);
SetRect(&sprite[kWalkRightFace].mask, 224, 0, 256, 32);
SetRect(&sprite[kRunRightFace].face, 160, 0, 192, 32); // BTW, there are plenty more clam faces and masks in the 'PICT's,…
SetRect(&sprite[kRunRightFace].mask, 160, 0, 192, 32); // …if you feel you need rect setting practice. :-)
SetRect(&sprite[kDizzyRightFace1].face, 384, 0, 416, 32); // Hey look! Here's more now!
SetRect(&sprite[kDizzyRightFace1].mask, 384, 0, 416, 32);
SetRect(&sprite[kDizzyRightFace2].face, 384, 32, 416, 64);
SetRect(&sprite[kDizzyRightFace2].mask, 384, 0, 416, 32);
SetRect(&sprite[kDizzyLeftFace1].face, 416, 0, 448, 32);
SetRect(&sprite[kDizzyLeftFace1].mask, 416, 0, 448, 32);
SetRect(&sprite[kDizzyLeftFace2].face, 416, 32, 448, 64);
SetRect(&sprite[kDizzyLeftFace2].mask, 416, 0, 448, 32);
}
//-------------------------------------------------------------- SetTheCPorts
void SetTheCPorts(void) // Create the CGrafPorts and load their .portPixMap fields.
{
// Create BitMap for sprite masks. NOTE THIS IS A BITMAP!
CreateOffScreenBitMap (&masksRect, &masksPort);
LoadGraphic (rMasksID); // …load 'PICT' resource for the clam masks.
// Create PixMap for Jane faces.
CreateOffScreenPixMap (&janeFacesRect, &janeFacesCPort);
LoadGraphic (bestJaneFacesID); // …load 'PICT' resource for the clam faces.
// Create PixMap for Clem faces.
CreateOffScreenPixMap (&clemFacesRect, &clemFacesCPort);
LoadGraphic (bestClemFacesID); // …load 'PICT' resource for the clam faces.
// Create PixMap for the background.
CreateOffScreenPixMap (&bigPictureRect, &backgroundCPort);
LoadGraphic(bestBackgroundID); // …load 'PICT' resource for the background picture.
// Create PixMap for offscreen graphics work.
CreateOffScreenPixMap (&bigPictureRect, &workCPort);
OpenMainWindow();
//{This fills the main window with the background picture, so the user can see it.
CopyBits(&((GrafPtr)backgroundCPort)->portBits,
&((GrafPtr)mainWindow)->portBits,
&bigPictureRect, &bigPictureRect, srcCopy, mainWindow->visRgn);
// This fills the workCPort.portPixMap with the background picture, so updates can be done quickly.
CopyBits(&((GrafPtr)backgroundCPort)->portBits,
&((GrafPtr)workCPort)->portBits,
&bigPictureRect, &bigPictureRect, srcCopy, mainWindow->visRgn);
}
//-------------------------------------------------------------- CopyBothAtOnce
void CopyBothAtOnce (void) //Display the clams on the screen when they're close together.
{
//UnionRect(clemComboRect, larryComboRect, allComboRect);
//{Find the smallest rectangle which will cover Larry and Clem.}
UnionRect(&janeComboRect, &clemComboRect, &allComboRect);
// Find the smallest rectangle which will cover the old position of Clem and the new.
//CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, allComboRect, allComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
CopyBits(&((GrafPtr)workCPort)->portBits,
&(((GrafPtr)mainWindow)->portBits),
&allComboRect, &allComboRect, srcCopy, mainWindow->visRgn);
//CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, allComboRect, allComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
//{Restore the workPort by covering up our clams with the background they obscure. This way, workPort is…}
CopyBits(&((GrafPtr)backgroundCPort)->portBits,
&(((GrafPtr)workCPort)->portBits),
&allComboRect, &allComboRect, srcCopy, mainWindow->visRgn);
// Restore the workCPort by covering up our clam with the background it obscures.
// This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
// without having to copy the entire PixMap.
}
//-------------------------------------------------------------- CopyOneAtATime
void CopyOneAtATime (void) // Display the clams on the screen when they're far apart.
{
//CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, larryComboRect, larryComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
CopyBits(&((GrafPtr)workCPort)->portBits,
&(((GrafPtr)mainWindow)->portBits),
&janeComboRect, &janeComboRect, srcCopy, mainWindow->visRgn);
// Copy the contents of janeComboRect from workCPort->portPixMap to the main window. In one swell foop, old Jane…
//…will be erased, and the new Jane overlayed onto the background picture. Wallah! Flicker-free animation!
//CopyBits(BitMapPtr(workMapC^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, clemComboRect, clemComboRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
CopyBits(&((GrafPtr)workCPort)->portBits,
&(((GrafPtr)mainWindow)->portBits),
&clemComboRect, &clemComboRect, srcCopy, mainWindow->visRgn);
// Copy the contents of clemComboRect from workCPort->portPixMap to the main window. In one swell foop, old Clem
//…will be erased, and the new Clem overlayed onto the background picture. Wallah! Flicker-free animation!
//CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, larryRect, larryRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
CopyBits(&((GrafPtr)backgroundCPort)->portBits,
&(((GrafPtr)workCPort)->portBits),
&janeIsAtRect, &janeIsAtRect, srcCopy, mainWindow->visRgn);
// Restore the workCPort by covering up Jane's image with the background it obscures.
// This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
// without having to copy the entire PixMap.
CopyBits(&((GrafPtr)backgroundCPort)->portBits,
&(((GrafPtr)workCPort)->portBits),
&clemIsAtRect, &clemIsAtRect, srcCopy, mainWindow->visRgn);
// Restore the workCPort by covering up Clem's image with the background it obscures.
// This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
// without having to copy the entire PixMap.
//CopyBits(BitMapPtr(backgroundMapC^.portPixMap^)^, BitMapPtr(workMapC^.portPixMap^)^, clemRect, clemRect, srcCopy, GrafPtr(mainWndo)^.visRgn);
}
//-------------------------------------------------------------- ShowClam
void ShowClams (void) // Do the animation and make it appear on the screen.
{
Rect dummyRect;
CopyMask(&((GrafPtr)janeFacesCPort)->portBits,
&((GrafPtr)masksPort)->portBits,
&((GrafPtr)workCPort)->portBits,
&sprite[janeSprite].face,
&sprite[janeSprite].mask,
&janeIsAtRect);
// Now there is an image of a clam in the new position in workMap. If we had done this work in…
// mainWindow, we would have seen considerable flickering. Instead, we did it offscreen, and left the…
// previous image of the clam visible on the screen while we worked.
UnionRect(&janeWasAtRect, &janeIsAtRect, &janeComboRect);
// Find the smallest rectangle which will cover the old position of Jane and the new.
CopyMask(&((GrafPtr)clemFacesCPort)->portBits,
&((GrafPtr)masksPort)->portBits,
&((GrafPtr)workCPort)->portBits,
&sprite[clemSprite].face,
&sprite[clemSprite].mask,
&clemIsAtRect);
// Now there is an image of a clam in the new position in workMap. If we had done this work in…
// mainWindow, we would have seen considerable flickering. Instead, we did it offscreen, and left the…
// previous image of the clam visible on the screen while we worked.
UnionRect(&clemWasAtRect, &clemIsAtRect, &clemComboRect);
// Find the smallest rectangle which will cover the old position of Clem and the new.
if (SectRect(&clemIsAtRect, &janeIsAtRect, &dummyRect))
{
contactFlag = TRUE;
CopyBothAtOnce();
}
else
{
contactFlag = FALSE;
CopyOneAtATime();
}
}
// CopyBits(&((GrafPtr)workCPort)->portBits,
//&(((GrafPtr)mainWindow)->portBits),
//&clamComboRect, &clamComboRect, srcCopy, mainWindow->visRgn);
// Copy the contents of comboRect from workCPort->portPixMap to the main window. In one swell foop, the old clam…}
//…will be erased, and the new clam overlayed onto the background picture. Wallah! Flicker-free animation!}
//CopyBits(&((GrafPtr)backgroundCPort)->portBits,
//&(((GrafPtr)workCPort)->portBits),
//&clamIsAtRect, &clamIsAtRect, srcCopy, mainWindow->visRgn);
// Restore the workCPort by covering up our clam with the background it obscures.
// This way, workCPort->portPixMap is identical to backgroundCPort->portPixMap,…
// without having to copy the entire PixMap.
//}
//-------------------------------------------------------------- DoDelay
// This is the companion function to the above function (LogNextTick()).
// We do nothing but loop until TickCount() catches up with (or passes) our…
// global variable tickNext.
void DoDelay (void)
{
do
{
}
while (TickCount() < targetTick); // Loop until TickCount() catches up.
targetTick = TickCount() + kWaitTicks;
}
//-------------------------------------------------------------- JaneLoop
void JaneLoop (void)
{
switch (janeSprite) //If the current view of jane is…
{ case (kStepRightFace): // …kStepRightFace, then set thisSprite to…
{ janeSprite = kWalkRightFace; // …kWalkRightFace, and if it is currently…
break; }
case (kWalkRightFace): // …kWalkFace, then set it to…
{ janeSprite = kRunRightFace; // …kRunRightFace.
break; }
// And if it was neither kStepRightFace nor kWalkRightFace, then janeSprite was either…
default : // …kRunRightFace, or what it was when RunRight()…
janeSprite = kStepRightFace; // …was called, so we set it to kStepRightFace
}
janeWasAtRect = janeIsAtRect; // Store the clam's current position as its last position,…
// …we'll be erasing it next time through the loop.
OffsetRect(&janeIsAtRect, kJaneStepLength, 0); // Set the clam's next position--it'll be…
// …kStepLength pixels to the right of its last position.
if (janeIsAtRect.left > 512) // If the clam has wandered out of sight,…
{ // …set the right border of clamIsAtRect…
janeIsAtRect.right = 0; // …to the left edge of the screen…
janeIsAtRect.left = -32; // …and move the left border of clamIsAtRect…
} // …as needed to maintain its 32 x 32 shape & size.
}
//-------------------------------------------------------------- ClemLoop
void ClemLoop (void)
{
switch (clemSprite) //If the current view of Clem is…
{ case (kStepRightFace): // …kStepRightFace, then set thisSprite to…
{ clemSprite = kWalkRightFace; // …kWalkRightFace, and if it is currently…
break; }
case (kWalkRightFace): // …kWalkFace, then set it to…
{ clemSprite = kRunRightFace; // …kRunRightFace.
break; }
// And if it was neither kStepRightFace nor kWalkRightFace, then clemSprite was either…
default : // …kRunRightFace, or what it was when RunRight()…
clemSprite = kStepRightFace; // …was called, so we set it to kStepRightFace
}
clemWasAtRect = clemIsAtRect; // Store the clam's current position as its last position,…
// …we'll be erasing it next time through the loop.
OffsetRect(&clemIsAtRect, kClemStepLength, 0); // Set the clam's next position--it'll be…
// …kStepLength pixels to the right of its last position.
if (clemIsAtRect.left > 512) // If the clam has wandered out of sight,…
{ // …set the right border of clamIsAtRect…
clemIsAtRect.right = 0; // …to the left edge of the screen…
clemIsAtRect.left = -32; // …and move the left border of clamIsAtRect…
} // …as needed to maintain its 32 x 32 shape & size.
if (clemSprite == kStepRightFace) // Only sound a footstep in pose where foot strikes ground.
PlayASound(rFootstepSndID, kLowSoundPriority); //Ahh, the pitter patter of tiny feet.
}
//-------------------------------------------------------------- JaneSpeaks
// This routine has the clam stop moving, face the screen, and move its face.
void JaneSpeaks (void)
{ Rect dummyRect;
if ((impactReadyFlag) && (SectRect(&janeIsAtRect, &clemIsAtRect, &dummyRect)))
DoImpact();
thisFaceCounter = thisFaceCounter + 1;
switch (thisFaceCounter)
{ case (1):
{ janeSprite = kFrontFace;
break; }
case (2):
{ janeSprite = kEehFace;
break; }
case (3): // This keeps an impact from occurring when both clams are in the same…
{ if (!(SectRect(&janeIsAtRect, &clemIsAtRect, &dummyRect))) // …place when the…
impactReadyFlag = TRUE; // …button is pushed.
break; }
case (4):
{ janeSprite = kFrontFace;
break; }
case (5):
{ janeSprite = kOohFace;
break; }
case (9):
{ janeSprite = kEehFace;
break; }
case (11):
{ janeSprite = kOohFace;
break; }
case (13):
{ janeSprite = kFrontFace;
break; }
case (16):
{ janeSprite = kBlinkFace;
break; }
case (18):
{ janeSprite = kFrontFace;
break; }
case (35):
{ janeSprite = kBlinkFace;
break; }
case (38):
{ janeSprite = kFrontFace;
break; }
case (39):
{ impactReadyFlag = TRUE;
break; }
}
}
//-------------------------------------------------------------- DoImpact
void DoImpact (void)
{
janeWasAtRect = janeIsAtRect; // Store the clam's current position as its last position.
OffsetRect(&janeIsAtRect, kJaneStepLength, 0); // Set the clam's next position.
clemWasAtRect = clemIsAtRect; // Store the clam's current position as its last position.
OffsetRect(&clemIsAtRect, kClemStepLength * kBounce, 0); // Set the clam's next position.
PlayASound(rImpactSndID, kHighestSoundPriority); // High enough to interrupt anything.
thisFaceCounter = 0;
while (thisFaceCounter <= kLastFace)
{
ShowClams();
DoDelay(); // Do nothing for a while.
PlayLoopSound(rDizzySndID, kHighSoundPriority); // Not high enough to interrupt the impact.
thisFaceCounter = thisFaceCounter + 1;
evenFrame = !evenFrame;
if (evenFrame)
{
janeSprite = kDizzyLeftFace1;
clemSprite = kDizzyRightFace1;
}
else
{
janeSprite = kDizzyLeftFace2;
clemSprite = kDizzyRightFace2;
}
}
gameOverFlag = TRUE; // And we're outta here. Game over.
}
//-------------------------------------------------------------- main
//----------------------------------------------------------------------
void main(void)
{
InitAll();
while (!Button()) // Before the user presses the mouse button, nothing happens.
{
}
while (Button()) // When the user presses the mouse button, nothing happens.
{
}
while (!Button()) // When the mouse button is released, continue to…
{
ShowClams(); // Put the clams on the screen.
DoDelay(); // Keep everything from happening too fast.
JaneLoop(); // Put Jane in her next position.
ClemLoop(); // Put Clem in his next position.
}
PlayASound(rHelloSndID, kMediumSoundPriority); // Sound, "Hello" when button is pushed.
while (!(gameOverFlag)) // …until the clams crash into each other and fall down dizzy.
{
ShowClams(); // Put the clams on the screen.
DoDelay(); // Keep everything from happening too fast.
JaneSpeaks(); // Make mouth motions, shift into impact mode when ready.
ClemLoop(); // Put Clem in his next position.
}
CloseDownSound();
InitCursor(); // Rarely needed, since most programs call InitCursor on startup. Still, it's…
// a good habit to leave everything in normal condition when your programs quit.
} // And we're done.
//------------------------------------------------------------------------------------------\\
// End HelloWorld5.c \\
//------------------------------------------------------------------------------------------\\